-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement parsing for records #40467
Conversation
282e10a
to
6d069ea
Compare
73ed2cc
to
336907b
Compare
83ff132
to
5b6c6dd
Compare
As agreed in LDM, the specification requires that a data contextual keyword be present in front of the class and a parameter list to be present after the identifier, for the type to be a record. The absence of either of these two elements will be a semantic error, not a parsing error.
5b6c6dd
to
dc69d22
Compare
// | ||
// | |d|yy|xxxxxxxxxxxxxxxxxxxxxxx|wwwwww| | ||
// | |vvv|zzzz|f|d|yy||wwwwww| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| [](start = 48, length = 1)
Extra vertical bar #Closed
@@ -1485,6 +1527,8 @@ private TypeDeclarationSyntax ParseClassOrStructOrInterfaceDeclaration(SyntaxLis | |||
semicolon); | |||
|
|||
case SyntaxKind.InterfaceKeyword: | |||
RoslynDebug.Assert(openBrace != null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RoslynDebug [](start = 24, length = 11)
I don't see how this assertion is correct. It appears that the above code would accept interface A;
I think we either need to make the curly braces optional or make missing tokens for them with an error. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly this code appears to be dropping the parameter list on the floor. I think it needs to be either added to the syntax, not permitted by the parser, or you need to build a class declaration when that happens.
In reply to: 361761780 [](ancestors = 361761780)
parameterList, | ||
baseList, | ||
constraintClauses, | ||
openBraceToken: default, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
default [](start = 32, length = 7)
I suspect you intended this to be the creation of a fresh semicolon token if there were no members, or fresh brace tokens if there were. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, since you don't know the language version at this point, perhaps this should create brace tokens always.
In reply to: 361762456 [](ancestors = 361762456)
default, | ||
members, | ||
default, | ||
default); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
default [](start = 16, length = 7)
I suspect you intended this to be the creation of a fresh semicolon token if there were no members, or fresh brace tokens if there were.
@@ -156,7 +156,7 @@ public void DeeplyNestedGeneric() | |||
(ExecutionArchitecture.x86, ExecutionConfiguration.Debug) => 270, | |||
(ExecutionArchitecture.x86, ExecutionConfiguration.Release) => 1290, | |||
(ExecutionArchitecture.x64, ExecutionConfiguration.Debug) => 170, | |||
(ExecutionArchitecture.x64, ExecutionConfiguration.Release) => 730, | |||
(ExecutionArchitecture.x64, ExecutionConfiguration.Release) => 700, // PROTOTYPE(angocke): Improve stack usage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// PROTOTYPE(angocke): Improve stack usage [](start = 84, length = 42)
I wouldn't bother.
public class RecordTests : CompilingTestBase | ||
{ | ||
[Fact] | ||
public void RecordLanguageVersion() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RecordLanguageVersion [](start = 20, length = 21)
Also try class Point;
. That should not be permitted in older language versions either.
Do you have a document that describes the feature this is intended to implement? Neither https://github.com/dotnet/csharplang/blob/master/proposals/records.md nor https://github.com/dotnet/csharplang/blob/master/proposals/recordsv2.md seems to be right. |
One of the things I'd be looking for in the specification is how you will modify the syntax and parser to handle constructor parameters of the base type. Without knowing how that's going to be handled, I cannot know if these parser changes implement the intended design. In reply to: 569365350 [](ancestors = 569365350) |
Finished review pass (Iteration 2). |
@@ -17,7 +17,7 @@ | |||
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder> | |||
<ToolsetPackagesDir>$(RepoRoot)build\ToolsetPackages\</ToolsetPackagesDir> | |||
|
|||
<RoslynPortableTargetFrameworks>net472;netcoreapp2.1</RoslynPortableTargetFrameworks> | |||
<RoslynPortableTargetFrameworks>netcoreapp2.1;net472</RoslynPortableTargetFrameworks> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please revert this change. Quoting from @jaredpar a few months ago:
We need to keep net472 as the first TF listed because that controls items like which tests run by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's the point. We should swap the default. I can't test on Mac using VS Code unless it's first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should swap the default. I can't test on Mac using VS Code unless it's first.
Definitely don't want us to do this. As @333fred noted, the order here is deliberate. Changing it will not fix anything, instead it will just fix one scenario and break another. In this case it would be fixing Mac, the minority scenario, and breaking Windows, the dominant scenario.
Where is the bug on VS Code that prevents Mac testing here? Have you filed a bug?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would it break Windows? The test explorer seems to work fine. Doesn't look like there's a bug here for VS Code. They don't support debugging on anything but .NET Core, and switching between target frameworks isn't a bug, it's a feature they don't have.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would it break Windows?
The set of tests run for desktop and core are significantly different. Moving to core by default will break the expectations of developers that expect to get the desktop tests.
If you think the trade off is a good one here then the correct course of action is to discuss the policy with the team. Not change it subtly in a PR. Particularly since this has come up several times before and we've kept the current order for these reasons.
Doesn't look like there's a bug here for VS Code.
VS Code cannot test code that every other tool in our toolbox can test. Is the explicit design of VS Code that they can't support multi-targeted projects? If so that seems really unfortunate.
it's a feature they don't have.
Where is the issue tracking the feature request?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you think the trade off is a good one here then the correct course of action is to discuss the policy with the team. Not change it subtly in a PR. Particularly since this has come up several times before and we've kept the current order for these reasons.
Yup, this is just going into a feature branch. I had planned to send an email out before changing it in master. Can I leave a PROTOTYPE comment above and we can do that when I'm back in Seattle?
Where is the issue tracking the feature request?
One thing we have to change for that is running our desktop tests as 64-bit by default. For the life of me I cannot figure out how to change that from 32-bit. I gave up after a couple hours.
You aren't doing anything wrong. x86 debugging is not supported by the C# extension. You will need full Visual Studio for that.
Beyond that, I'm not sure what feature we would be asking for. Some way to change the framework the tests are run under? VS only got that a couple months ago, so it's not exactly something I'd put at the top of the VS Code priority list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can I leave a PROTOTYPE comment above and we can do that when I'm back in Seattle?
That's fine by me.
Beyond that, I'm not sure what feature we would be asking for. Some way to change the framework the tests are run under?
I think the ask is pretty straight forward: we have a project which is multi-targeted to desktop and .NET Core. When that happens don't fail, instead prefer the .NET Core target framework. Basically do the only action which is capable of succeeding in this environment.
Done review pass (commit 2) |
SyntaxToken semicolon; | ||
SyntaxToken? openBrace; | ||
SyntaxToken? closeBrace; | ||
if (isInterface || CurrentToken.Kind != SyntaxKind.SemicolonToken) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CurrentToken.Kind != SyntaxKind.SemicolonToken [](start = 35, length = 46)
I feel like this isn't a great solution. I know this change was prompted by Neal, but I feel like a better solution would be to parse the interface as a record declaration, and then issue a semantic error for "Interfaces cannot be records."
comp.VerifyDiagnostics(); | ||
comp = CreateCompilation(src2, parseOptions: TestOptions.RegularPreview); | ||
comp.VerifyDiagnostics(); | ||
comp = CreateCompilation(src3, parseOptions: TestOptions.RegularPreview); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing a VerifyDiagnostics
Done review pass (commit 5) |
Similarly, I would expect to see a syntax tree and parsing for the "constructor body" from https://github.com/dotnet/csharplang/blob/master/proposals/records.md#primary-constructor-body (which incidentally was copied verbatim into Java's record feature). In reply to: 569365766 [](ancestors = 569365766,569365350) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good as a partial implementation of parsing for what I expect a record specification to look like based on recent discussions. If my expectations are wrong then I'd want to review this code again with respect to whatever the specification actually is. To save us all from having to re-review code going forward, please provide a specification of this feature.
@gafter Good point, I've added https://github.com/dotnet/csharplang/blob/master/proposals/records-wip.md Basically, I intend to support the syntax that you linked, with the added |
I recommend reviewing the first commit separately. All it does is split DeclarationModifiers into its own field in our flags structs since we ran out of space, and splitting the modifiers out was simpler and clearer. The second commit actually implements the parsing.
As agreed in LDM, the specification requires that a data contextual
keyword be present in front of the class and a parameter list to be
present after the identifier, for the type to be a record.
The absence of either of these two elements will be a semantic error,
not a parsing error.
Relates to #40726 (test plan for records)